package toXML;

import houseHold.House;
import houseHold.HouseHoldObject;
import houseHold.HouseHoldObjectFactory;
import houseHold.ObjectType;
import houseHold.Point2D;
import houseHold.Room;
import houseHold.TypeSelector;

import java.io.File;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import sensor.Sensor;
import sensor.SensorType;
import RoomPanel.IDGenerator;

public class LoadHouseXML {
	private static HouseHoldObject buildObject(Node n, Room currentRoom) {

		NamedNodeMap attributeList = n.getAttributes();
		/**
		 * Get object type to invoke factoryMethod
		 */
		String type = attributeList.getNamedItem("Type").getNodeValue();
		ObjectType oType = TypeSelector.getObjectType(type);
		HouseHoldObject newObject = HouseHoldObjectFactory.getObject(oType);
		/**
		 * Set Object Name & Type;
		 */
		String name = attributeList.getNamedItem("Name").getNodeValue();
		String s_id = name.substring(name.indexOf('#') + 1);
		int id = Integer.parseInt(s_id);
		newObject.setID(id);
		newObject.setType(oType, false);

		/**
		 * Get Point of origin
		 */
		NodeList list = n.getChildNodes();
		for (int i = 0; i < list.getLength(); i++) {
			Node next = list.item(i);

			if (next.getNodeName().equalsIgnoreCase("Consumption")) {
				/**
				 * Get Consumption
				 */
				NamedNodeMap consList = next.getAttributes();
				String value = consList.getNamedItem("Consumption")
						.getNodeValue();
				newObject.setConsumption(Integer.parseInt(value));
				String sensor = consList.getNamedItem("Sensor").getNodeValue();
				newObject.setSensor(currentRoom.getSensor(sensor));

			}
		}
		return newObject;
	}

	private static Room buildRoom(Node n) {
		Room nextRoom = new Room();
		NamedNodeMap attributeList = n.getAttributes();
		/**
		 * Reading Attributes from list;
		 */
		Node width = attributeList.getNamedItem("width");
		Node height = attributeList.getNamedItem("height");
		Node length = attributeList.getNamedItem("length");
		Node type = attributeList.getNamedItem("Type");
		Node name = attributeList.getNamedItem("Name");

		/**
		 * Setting room attributes;
		 */

		/**
		 * Setting dimensions
		 */
		nextRoom.setHeight(Integer.parseInt(height.getNodeValue()));
		nextRoom.setWidth(Integer.parseInt(width.getNodeValue()));
		nextRoom.setLength(Integer.parseInt(length.getNodeValue()));
		/**
		 * Setting Name
		 */
		nextRoom.setName(name.getNodeValue());
		System.out.println(nextRoom.getName());
		nextRoom.setID(Integer.parseInt(name.getNodeValue().substring(
				name.getNodeValue().indexOf('#') + 1)));
		/**
		 * Setting type
		 */
		nextRoom.setType(TypeSelector.getRoomType(type.getNodeValue()));

		/**
		 * Getting Child Nodes
		 */
		NodeList list = n.getChildNodes();
		for (int i = 0; i < list.getLength(); i++) {
			Node nextChild = list.item(i);
			if (nextChild.getNodeName().equalsIgnoreCase("Origin")) {
				/**
				 * If its the point of origin - Set it
				 */
				nextRoom.setOrigin(getPoint(nextChild));
			}
			if (nextChild.getNodeName().equalsIgnoreCase("Sensor")) {

				/**
				 * If its an sensor- Load it into the room;
				 */
				Sensor sensor = buildSensor(nextChild, nextRoom);
				nextRoom.addSensor(sensor);
			}
			if (nextChild.getNodeName().equalsIgnoreCase("Object")) {

				/**
				 * If its an object - Load it into the room;
				 */
				HouseHoldObject object = buildObject(nextChild, nextRoom);
				nextRoom.addItem(object);
			}
		}

		n.getChildNodes();

		/**
		 * Loading Objects;
		 */

		return nextRoom;
	}

	private static Sensor buildSensor(Node n, Room currentRoom) {

		NamedNodeMap attributeList = n.getAttributes();
		Sensor newSensor = new Sensor();
		/**
		 * Get sensor name & type
		 */
		String type = attributeList.getNamedItem("Type").getNodeValue();
		String name = attributeList.getNamedItem("Name").getNodeValue();
		/**
		 * Set Set Name & Type;
		 */

		newSensor.setSensorName(name);
		newSensor.setSensorID(Integer.parseInt(name
				.substring(name.indexOf('#') + 1)));
		newSensor.setType(SensorType.match(type));

		return newSensor;
	}

	private static Point2D getPoint(Node n) {
		Point2D p = new Point2D();
		NamedNodeMap pointData = n.getAttributes();
		String x = pointData.getNamedItem("X").getNodeValue();
		String y = pointData.getNamedItem("Y").getNodeValue();
		p = new Point2D(Integer.parseInt(x), Integer.parseInt(y));
		return p;
	}

	public static void loadXML(File f) {

		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db;
		try {
			db = dbf.newDocumentBuilder();
			Document doc = db.parse(f);
			doc.getDocumentElement().normalize();

			NodeList nodeList = doc.getElementsByTagName("House");
			Node n = nodeList.item(0);
			NamedNodeMap attributeList = n.getAttributes();
			Node objID = attributeList.getNamedItem("OBJECT_ID");
			Node roomID = attributeList.getNamedItem("ROOM_ID");
			Node sensID = attributeList.getNamedItem("SENSOR_ID");

			nodeList = doc.getElementsByTagName("Room");
			for (int i = 0; i < nodeList.getLength(); i++) {
				Room nextRoom = buildRoom(nodeList.item(i));
				House.getInstance().addRoom(nextRoom);
			}
			IDGenerator.initIDS(Integer.parseInt(roomID.getNodeValue()),
					Integer.parseInt(objID.getNodeValue()), Integer
							.parseInt(sensID.getNodeValue()));
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
